/*
 * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "lega_at_api.h"
#include "app.h"

extern int init_ble_task(void);
extern bool check_ble_task(void);
extern int ble_close(void);
static uint8_t gAtBle_open = 0;


bool atcmd_is_ble_open()
{
    if (gAtBle_open == 1)
    {
        return true;
    }
    return false;
}

void atcmd_set_ble_open(uint8_t value)
{
    gAtBle_open = value;
}


static uint8_t string_asc_to_hex(char param)
{
    uint8_t val;

    if((param >= 48) && (param <= 57))
        val = param-48;
    else if((param >= 65) && (param <= 70))
        val = param-55;
    else if((param >= 97) && (param <= 102))
        val = param-87;
    else
    {
        val = 0xA;
    }
    return val;
}

static void sonata_string_to_array(char *input_str, uint8_t input_length,uint8_t *hex_addr)
{
    int i;
    input_length = (input_length + 1) &0xFFFE;
    for(i = 0; i < input_length; i++)
    {
        if(i%2 || i==1)
            hex_addr[i>>1] = string_asc_to_hex(input_str[i]) | (hex_addr[i>>1]&0xF0);
        else
            hex_addr[i>>1] = (string_asc_to_hex(input_str[i])<<4) | (hex_addr[i>>1]&0xF);
    }
}


static int lega_at_ble_open(int argc, char **argv)
{
    if(gAtBle_open == 0)
    {
        init_ble_task();
        gAtBle_open = 1;
    }
    else
    {
        printf("ble is alread open!\n");
    }
    return 0;
}
static int lega_at_ble_close(int argc, char **argv)
{
    if (gAtBle_open == 1)
    {
        gAtBle_open = 0;
        ble_close();
    }
    else
    {
        printf("ble don't need close!\n");
    }
    return 0;
}
//for adv demo
#if 1
uint8_t  gtest_adv_value[32] = {0x08,0x09,0x41,0x53,0x52,0x2D,0X42,0X4C,0X45};
uint8_t  gtest_adv_length = 9;
#endif
static int lega_at_ble_adv(int argc, char **argv)
{

    ble_adv_data_t adv_data_stu = {0};
    // ble_scan_data_t scan_data = {0};
    //scan_data.respdataLen = rsp_len;
    // memcpy(scan_data.respdata,rsp_data,rsp_len);

    if(strcmp(argv[1],"start")==0 && argc == 2)
    {
        printf("adv demo start!!!!!!!!!!! \r\n");
        adv_data_stu.ble_advdataLen = gtest_adv_length;
        memcpy(adv_data_stu.ble_advdata,gtest_adv_value,gtest_adv_length);
        app_ble_advertising_start(0,&adv_data_stu,0);
    }
    else if(strcmp(argv[1],"start")==0 && argc > 2)
    {
        printf("adv start!!!!!!!!!!! \r\n");
        uint8_t hex_value[32];
        memset(hex_value,0,32);
        uint16_t hex_length = (strlen(argv[2]) + 1)/2;
        sonata_string_to_array(argv[2] ,strlen(argv[2]),hex_value);
        adv_data_stu.ble_advdataLen = hex_length;
        memcpy(adv_data_stu.ble_advdata,hex_value,hex_length);
        app_ble_advertising_start(0,&adv_data_stu,0);
    }
    else if(strcmp(argv[1],"stop")==0)
    {
        printf("adv stop!!!!!!!!!!! \r\n");
        app_ble_advertising_stop(0);
    }
    return 0;
}

static int lega_at_ble_scan(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0)
    {
        printf("at scan start!!!!!!!!!!! \r\n");
        sonata_api_app_timer_set(9,20);
    }
    else if(strcmp(argv[1],"stop")==0)
    {
        printf("at scan stop!!!!!!!!!!! \r\n");
        app_ble_scan_stop();
    }

    return 0;
}

static int lega_at_ble_connect(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0 && argc > 2)
    {
        printf("at connect start!!!!!!!!!!! \r\n");
        uint8_t hex_value[6];
        sonata_string_to_array(argv[2] ,strlen(argv[2]),hex_value);
        app_ble_set_target_addr(hex_value);
        app_ble_start_connect(SONATA_GAP_STATIC_ADDR);
    }
    else if(strcmp(argv[1],"stop")==0)
    {
        printf("at connect stop!!!!!!!!!!! \r\n");
        app_ble_disconnect();
    }
    return 0;
}

static int lega_at_ble_mtu(int argc, char **argv)
{
    if(strcmp(argv[1],"set")==0 && argc > 2)
    {
        printf("at mtu set!!!!!!!!!!! \r\n");
        uint16_t value = atoi(argv[2]);
        app_ble_set_max_mtu(value);

    }
    else if(strcmp(argv[1],"exchange")==0)
    {
        printf("at mtu exchange!!!!!!!!!!! \r\n");
        sonata_ble_gatt_exchange_mtu(0);

    }
    else if(strcmp(argv[1],"get")==0)
    {
        uint16_t value = app_ble_get_mtu(0);
        printf("mtu: 0x%08x!!!!!!!!!!! \r\n",value);
    }
    return 0;
}

static int lega_at_ble_con_update(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0)
    {
        printf("at connect params set!!!!!!!!!!! \r\n");
        uint8_t conidx = atoi(argv[2]);
        uint16_t intv_min = atoi(argv[3]);
        uint16_t intv_max = atoi(argv[4]);
        uint16_t latency = atoi(argv[5]);
        uint16_t timeout = atoi(argv[6]);
        sonata_ble_gap_update_connection_params(conidx, 0, intv_min, intv_max,
                                        latency, timeout, 0x8, 0x8);
    }
    return 0;
}

static void lega_at_ble_add_service(int argc, char **argv)
{
}
static int lega_at_ble_disc_serv(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0 && argc == 2)
    {
        printf("at discorver all service!!!!!!!!!!! \r\n");
        sonata_ble_gatt_disc_all_svc(0);
    }
    else if(strcmp(argv[1],"start")==0 && argc > 2)
    {
        printf("at discorver service by uuid!!!!!!!!!!! \r\n");
        uint8_t uuid[2];
        sonata_string_to_array(argv[2] ,strlen(argv[2]),uuid);
        for(int i=0; i<2; i++)
        {
            printf("uuid:%x",uuid[i]);
        }
        sonata_ble_gatt_disc_svc_by_uuid(0, 0, 0xFFFF, SONATA_ATT_UUID_16_LEN, uuid);
    }

    return 0;
}

static int lega_at_ble_disc_char(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0 && argc == 2)
    {
        printf("at discorver all char!!!!!!!!!!! \r\n");
        sonata_ble_gatt_disc_all_characteristic(0, 1, 0xFFFF);
    }
    else if(strcmp(argv[1],"start")==0 && argc > 2)
    {
        printf("at discorver char by uuid!!!!!!!!!!! \r\n");
        uint8_t conidx = atoi(argv[2]);
        uint16_t start_handle = atoi(argv[3]);
        uint16_t end_handle = atoi(argv[4]);
        uint8_t uuid[2];
        sonata_string_to_array(argv[5] ,strlen(argv[5]),uuid);
        for(int i=0; i<2; i++)
        {
            printf("uuid:%x",uuid[i]);
        }
        sonata_ble_gatt_disc_characteristic_by_uuid( conidx, start_handle, end_handle, SONATA_ATT_UUID_16_LEN, uuid);
    }

    return 0;
}

static int lega_at_ble_disc_desc(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0)
    {
        printf("at discorver all desc!!!!!!!!!!! \r\n");
        uint8_t conidx = atoi(argv[2]);
        uint16_t start_handle = atoi(argv[3]);
        uint16_t end_handle = atoi(argv[4]);
        sonata_ble_gatt_disc_all_descriptor(conidx, start_handle, end_handle);
    }
    return 0;
}

static int lega_at_ble_gatt_write(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0)
    {
        printf("at gatt write!!!!!!!!!!! \r\n");
        uint8_t type = atoi(argv[2]);
        uint16_t conn_hdl = atoi(argv[3]);
        uint16_t att_handle = atoi(argv[4]);
        uint16_t len = atoi(argv[5]);
        uint8_t data[32];
        sonata_string_to_array(argv[6] ,strlen(argv[6]),data);
        sonata_ble_gatt_write(conn_hdl, att_handle, 0, 0, len, data);
    }
    return 0;
}

static int lega_at_ble_data_send(int argc, char **argv)
{
    if(strcmp(argv[1],"start")==0)
    {
        printf("at data_send!!!!!!!!!!! \r\n");
        uint8_t conidx = atoi(argv[2]);
        uint16_t local_handle = atoi(argv[3]);
        uint16_t idx = atoi(argv[4]);
        uint16_t length = atoi(argv[5]);
        uint8_t data[32];
        sonata_string_to_array(argv[6] ,strlen(argv[6]),data);
        app_ble_gatt_data_send(conidx,local_handle,idx,length,data);
    }
    return 0;
}
cmd_entry comm_ble_open = {
        .name = "ble_open", .help ="cmd format:   ble_open\r\n\cmd function: open ble as slave and boardcast\r\n",
        .function = lega_at_ble_open,
};

cmd_entry comm_ble_close = {
        .name = "ble_close", .help ="cmd format:   ble_close\r\n\ cmd function: close ble boardcast\r\n",
        .function = lega_at_ble_close,
};

cmd_entry comm_ble_adv = {
        .name = "adv", .help ="adv start|stop [adv data] [rsp data]",
        .function = lega_at_ble_adv,
};

cmd_entry comm_ble_scan ={
        .name     = "scan", .help = "scan start|stop",
        .function = lega_at_ble_scan,
};

cmd_entry comm_ble_connect ={
        .name     = "connect", .help = "connect start|stop [target_addr]",
        .function = lega_at_ble_connect,
};

cmd_entry comm_ble_mtu ={
        .name     = "mtu", .help = "mtu set|get|exchange [value]",
        .function = lega_at_ble_mtu,
};

cmd_entry comm_ble_con_update ={
        .name     = "con_update", .help = "con_update start [params]",
        .function = lega_at_ble_con_update,
};

cmd_entry comm_ble_add_service ={
        .name     = "add_service_test", .help = "add_service_test",
        .function = lega_at_ble_add_service,
};
cmd_entry comm_ble_disc_serv ={
        .name     = "discovery_serv", .help = "discovery_serv start [params]",
        .function = lega_at_ble_disc_serv,
};


cmd_entry comm_ble_disc_char ={
        .name     = "discovery_char", .help = "discovery_char start [params]",
        .function = lega_at_ble_disc_char,
};

cmd_entry comm_ble_disc_desc ={
        .name     = "discovery_desc", .help = "discovery_desc start [params]",
        .function = lega_at_ble_disc_desc,
};

cmd_entry comm_ble_write ={
        .name     = "gatt_write", .help = "gatt_write start [params]",
        .function = lega_at_ble_gatt_write,
};

cmd_entry comm_ble_notify ={
        .name     = "data_send", .help = "data_send start [params]",
        .function = lega_at_ble_data_send,
};




void lega_at_ble_cmd_register(void)
{
    lega_at_cmd_register(&comm_ble_open);
    lega_at_cmd_register(&comm_ble_close);
    lega_at_cmd_register(&comm_ble_adv);
    lega_at_cmd_register(&comm_ble_scan);
    lega_at_cmd_register(&comm_ble_connect);
    lega_at_cmd_register(&comm_ble_con_update);
    lega_at_cmd_register(&comm_ble_mtu);
    lega_at_cmd_register(&comm_ble_add_service);
    lega_at_cmd_register(&comm_ble_disc_serv);
    lega_at_cmd_register(&comm_ble_disc_char);
    lega_at_cmd_register(&comm_ble_disc_desc);
    lega_at_cmd_register(&comm_ble_write);
    lega_at_cmd_register(&comm_ble_notify);
}



